今天來介紹通訊協定WebSocket
吧,最近都會想主題想一陣子才知道要寫什麼,各種前輩的文章翻來翻去,好就介紹這個吧ˊˇˋ
先看一下wiki
介紹
WebSocket
是一種網路傳輸協定,可在單個TCP
連接上進行全雙工通訊,位於OSI
模型的應用層。
WebSocket
使得客戶端和伺服器之間的資料交換變得更加簡單,允許伺服器端主動向客戶端推播資料。在WebSocket
中,只需要完成一次交握,兩者之間就可以建立永續性的連接,並進行雙向資料傳輸。
在http
中,client
請求server
回應,連線就會中斷了,若是server
有更新要傳回,也只能等client
發出請求才能回應。若是傳輸頻率很高,就必須讓client
不斷發出請求,在效能上的表現並不好,也不能真正取得即時訊息。
而能夠即時通訊的WebSocket
協定就在2008年因應而生。
WebSocket
是雙向通訊模式,在client
送出handshake
(握手)建立連線後,即開始雙向模式互動,client
與server
端都能隨時將資料傳給對方,直到disconnect
為止。
我們比較一下WebSocket
與http
兩種協定有什麼相似之處與相異之處
TCP
的一種傳輸協定OSI Layer7
協定Http
為單向通訊協議;Websocket
是雙向通訊。Http
為client
向server
發起連線;WebSocket
以Handshake
建立連線。Http
為短連線,請求結束後會釋放連線;WebSocket
建立連線後伺服器會持續監聽請求,不用每次重新連線。Go語言標準套件裡面沒有提供對WebSocket
的支援,這邊使用由Gorilla
團隊製作的WebSocket
套件,gorilla/websocket。
go get github.com/gorilla/websocket
import(
"github.com/gorilla/websocket"
)
package main
import (
"log"
"net/http"
"fmt"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{}
func socketHandler(w http.ResponseWriter, r *http.Request) {
// Upgrade our raw HTTP connection to a websocket based one
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("Error during connection upgradation:", err)
return
}
defer func() {
log.Println("disconnect !!")
conn.Close()
}()
// The event loop
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
log.Println("Error during message reading:", err)
break
}
log.Printf("Received: %s", message)
err = conn.WriteMessage(messageType, message)
if err != nil {
log.Println("Error during message writing:", err)
break
}
}
}
func home(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Index Page")
}
func main() {
http.HandleFunc("/socket", socketHandler)
log.Println("server start at :8080")
http.HandleFunc("/", home)
log.Fatal(http.ListenAndServe(":8080", nil))
}
寫完後可以將伺服器執行起來
這邊客戶端的功能是每隔一秒會往伺服器傳一次"WebSocket Success!"
package main
import (
"log"
"time"
"github.com/gorilla/websocket"
)
func main() {
conn, _, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8080/socket", nil)
if err != nil {
log.Fatal("dial:", err)
}
defer conn.Close()
for {
time.Sleep(time.Second)
err = conn.WriteMessage(websocket.TextMessage, []byte("WebSocket Success!"))
if err != nil {
log.Println(err)
return
}
_, msg, err := conn.ReadMessage()
if err != nil {
log.Println("read:", err)
return
}
log.Printf("receive: %s\n", msg)
}
}
客戶端這邊顯示
output:
2022/10/08 15:54:04 receive: WebSocket Success!
2022/10/08 15:54:05 receive: WebSocket Success!
.
.
.
伺服器端顯示
output:
2022/10/08 15:54:04 Received: WebSocket Success!
2022/10/08 15:54:05 Received: WebSocket Success!
.
.
.
一份WebSocket
測試完成了,這邊是最基礎的使用法
慢聊Go之GoLang中使用Gorilla Websocket|Go主题月
https://juejin.cn/post/6946952376825675812
Golang 如何建構一個 websocket server
https://ithelp.ithome.com.tw/articles/10208531
WebSocket
https://ithelp.ithome.com.tw/articles/10249282
WebSocket協議入門介紹
https://iter01.com/420761.html